﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace memcached.Tx
{
    /// <summary>
    /// We assume null is not a valid value.
    /// We assume the expiry information provided is valid for Rollback operations.
    /// </summary>
    internal sealed class SetExOp : SetOp
    {
        [System.Diagnostics.DebuggerHidden]
        public SetExOp(ICache real, ICacheAdvanced temp, string key, object value, DateTime expireAt)
            : base(real, temp, key, value)
        {
            ExpireAt = expireAt;
        }

        [System.Diagnostics.DebuggerHidden]
        public SetExOp(ICache real, ICacheAdvanced temp, string key, object value, int validFor)
            : base(real, temp, key, value)
        {
            ValidFor = validFor;
        }

        [System.Diagnostics.DebuggerHidden]
        public SetExOp(ICache real, ICacheAdvanced temp, string key, object value, ulong cas)
            : base(real, temp, key, value)
        {
            Cas = cas;
        }

        private readonly DateTime ExpireAt;

        private readonly int ValidFor;

        private readonly ulong Cas;

        public override string Name
        {
            [System.Diagnostics.DebuggerHidden]
            get { return "SetEx:" + Key; }
        }

        public override object Execute()
        {
            if (ValidFor > 0)
                return Temp.Set(Key, ValidFor, Value);
            if (ExpireAt > DateTime.MinValue)
                return Temp.Set(Key, ExpireAt, Value);
            return ((ICacheAdvanced)Temp).Set(Key, Cas, Value);
        }

        public override bool Persist()
        {
            // we assume failure means it was not updated,
            // but if anthing fails we need to restore the state in Rollback
            bool res;
            Original = Store.Get(Key, out res);
            if (res)
            {
                if (ValidFor > 0)
                    res = Store.Set(Key, ValidFor, Value);
                else
                    if (ExpireAt > DateTime.MinValue)
                        res = Store.Set(Key, ExpireAt, Value);
                    else
                        res = ((ICacheAdvanced)Store).Set(Key, Cas, Value);
            }
            Done = res;
            return res;
        }

        public override bool Rollback()
        {
            bool res;
            if (Done && Original != null)
            {
                if (ValidFor > 0)
                    res = Store.Set(Key, ValidFor, Original);
                else
                    if (ExpireAt > DateTime.MinValue)
                        res = Store.Set(Key, ExpireAt, Original);
                    else
                        res = ((ICacheAdvanced)Store).Set(Key, Cas, Original);
            }
            else res = true;
            return res;// if it was not set, than nothing to reset
        }
    }
}